/*
 * Copyright (c) 2017-2019, Lindenis Tech. Ltd.
 * All rights reserved.
 *
 * File:
 *
 * Description:
 *
 * Author:
 *      xiaoshujun@lindeni.com
 *
 * Create Date:
 *      2019/08/21
 *
 * History:
 *
 */

#ifndef __LIND_CAMERA__
#define __LIND_CAMERA__

#ifdef __cplusplus
extern "C" {
#endif

#include "osal_types.h"
#include "lindcomponent.h"

#define MULTI_VENC_CNT      3
#define MULTI_YUV_CNT       2
#define OSD_CNT             8

typedef struct _camera_config_t
{
    /*
     * msg callback
     */
    comm_msg_cb msg_cb;
    void * user;

    /*
     * Main channel capture size, framerate and rotate.
     */
    int cap_width;
    int cap_height;
    int framerate;

    /*
     * Sub channel capture size.
     */
    int cap_width_sub;
    int cap_height_sub;

    /*
     * video flip & mirror.
     */
    int flip;
    int mirror;
} camera_config_t;

typedef struct _preview_config_t
{
    disp_dev_e      device;

    /*
     * preview position
     */
    rect_t          pos;

    rotate_degree_e rotate;

    /*
     * the layer z-order
     *  range [0, 16]: from bottom to up
     */
    int             z_order;

    /*
     * channel id: 0 or 1
     *  0. Display engine has 2 video channels.
     *  1. Each video channel has 4 layers.
     *  2. All layers in the same channel must be the same attribution('format', 'size', 'scale ratio')
     *  3. Layers in different channel can be different attribution.
     *  4. Upto 4 different cameras with the same resolution can preview in the same channel.
     *  5. Cameras with the different resolution muset preview in the different channel.
     */
    int             channel_id;
} preview_config_t;

typedef struct _record_config_t
{
    /*
     * video recorder parameters.
     */
    av_enc_type_t venc_type;
    int venc_width;
    int venc_height;
    rect_t crop;
    int framerate;
    int bitrate;
    int gop;
    int venc_rotate;
    int venc_mirror;

    /*
     * 0:CBR 1:VBR 2:FIXQp 3:ABR 4:QPMAP
     */
    unsigned int rc_mode;
    unsigned int min_qp;
    unsigned int max_qp;

    /*
     * !!!
     * H264: 0:baseline, 1:MP, 2:HP, 3: SVC-T [0,3]
     * H265: 0:MP
     */
    unsigned int profile;

    /*
     * for net stream
     */
    int iframe_attach_spspps;

    // audio capture
    int channels;
    int sample_rate;
    int bits;
    av_enc_type_t aenc_type;

    /*
     * muxer parameters.
     */
    av_mux_type_t mux_type;
    int max_file_duration;  // unit: ms
    int max_file_size;      // unit: bytes

    /*
     * VE clock frequency
     */
    int ve_freq;
} record_config_t, venc_config_t;

typedef struct _picture_config_t
{
    int     width;
    int     height;
    int     quality;

    int     crop_enable;
    rect_t  crop;

    /*
     * write in exif
     */
    char    make[64];
    char    model[64];
} picture_config_t;

typedef enum _camera_osd_type_e
{
    LD_CAMERA_OSD_TYPE_UNKNOWN              = -1,
    LD_CAMERA_OSD_TYPE_BMP,
    LD_CAMERA_OSD_TYPE_STRING,
    LD_CAMERA_OSD_TYPE_DATE,
} camera_osd_type_e;

typedef struct _mpp_osd_config_t
{
    /*
     * 0: bmp set by app
     * 1: string set by app
     * 2: string of 'date' update in a internel thread
     */
    camera_osd_type_e   osd_type;

    /*
     * if 'osd_type' is 0, 'data' is bmp path
     * if 'osd_type' is 1, 'data' is the string to show
     * if 'osd_type' is 2, 'data' not use
     */
    char *              data;

    /*
     * start point position in capture frame
     */
    int                 left;
    int                 top;

    /*
     * font size for 'LD_CAMERA_OSD_TYPE_STRING'
     * available value: '16, 32, 64'
     */
    int                 font_size;
} mpp_osd_config_t;

typedef enum
{
    LD_CAMERA_MSG_UNKNOWN               = 0,

    //
    LD_CAMERA_MSG_TAKE_PICTURE          = 1,
    LD_CAMERA_MSG_TAKE_PICTURE_END      = 2,

    //
    LD_CAMERA_MSG_CB_ES                 = 3,
    LD_CAMERA_MSG_CB_YUV                = 4,

    //
    LD_CAMERA_MSG_RECORD_DONE           = 5,
    LD_CAMERA_MSG_RECORD_NEXT_FD        = 6,

    //
    LD_CAMERA_MSG_ERROR,
} mpp_cam_msg_e;

/**
 * Create a mpp camera object.
 *
 * @param
 * @return
 *    NULL: create failed.
 *    others: a mpp camera handle.
 */
_handle_t mpp_cam_create(int camera_id);

/**
 * Call mpp_cam_destroy to destroy the mpp camera object before exit the app.
 *
 * @param
 *    h_camera[in]: mpp camera handle
 * @return
 */
void mpp_cam_destroy(_handle_t h_camera);

/**
 * set camera parameters.
 *
 * @param
 *    p_config[in]: camera parameters
 * @return
 */
int  mpp_cam_set_params(_handle_t h_camera, camera_config_t * p_config);

/**
 * set color mode.
 *
 * @param
 *    mode[in]: 0: colorful(default), 1: white & black
 * @return
 */
int  mpp_cam_set_color_mode(_handle_t h_camera, int mode);

/**
 * set a value to up/down the brightness.
 *
 * @param
 *    value[in]: range: [-126, 126],
 *                      0(default)  : auto brigtness
 *                      [1, 126]    : up the brightness
 *                      [-126, -1]  : down the brightness
 * @return
 */
int  mpp_cam_set_brightness(_handle_t h_camera, int value);

/**
 * preview
 * 'mpp_cam_preview_start2()' support rotate preivew.
 */
int  mpp_cam_preview_set_params(_handle_t h_camera, preview_config_t * p_config);
int  mpp_cam_preview_start(_handle_t h_camera);
void mpp_cam_preview_stop(_handle_t h_camera);
int  mpp_cam_preview_start2(_handle_t h_camera);
void mpp_cam_preview_stop2(_handle_t h_camera);
int  mpp_cam_show_ui(_handle_t h_camera, int show);

/**
 * recording
 */
int  mpp_cam_record_set_params(_handle_t h_camera, record_config_t * p_config);
int  mpp_cam_record_start(_handle_t h_camera, char * filename);
int  mpp_cam_record_start_fd(_handle_t h_camera, int fd);
void mpp_cam_record_stop(_handle_t h_camera);
int  mpp_cam_record_switch_next_fd(_handle_t h_camera, int fd);
int  mpp_cam_record_set_crop(_handle_t h_camera, rect_t * crop);
void mpp_cam_record_disable_crop(_handle_t h_camera);
int  mpp_cam_record_set_mute(_handle_t h_camera, int mute);
int  mpp_cam_record_get_mute(_handle_t h_camera);

/**
 * taking picture
 */
int  mpp_cam_picture_channel_prepare(_handle_t h_camera);
int  mpp_cam_picture_set_params(_handle_t h_camera, picture_config_t * p_config);
int  mpp_cam_picture_taking(_handle_t h_camera, char * filename);
void mpp_cam_picture_channel_destroy(_handle_t h_camera);

/**
 * callback video es
 *
 * cb es support upto 3 different encoder parameters.
 * 'index' tell which one to use.
 */
int  mpp_cam_venc_set_params(_handle_t h_camera, int index, venc_config_t * p_config);
int  mpp_cam_venc_start(_handle_t h_camera, int index);
void mpp_cam_venc_stop(_handle_t h_camera, int index);
int  mpp_cam_venc_set_crop(_handle_t h_camera, int index, rect_t * crop);
void mpp_cam_venc_disable_crop(_handle_t h_camera, int index);
int  mpp_cam_venc_update_bitrate(_handle_t h_camera, int index, int bitrate);
void mpp_cam_venc_request_idr(_handle_t h_camera, int index);

/**
 * callback video yuv
 */
int  mpp_cam_yuv_start(_handle_t h_camera, int index);
void mpp_cam_yuv_stop(_handle_t h_camera, int index);

/**
 * osd
 */
int  mpp_cam_osd_set_params(_handle_t h_camera, int index, mpp_osd_config_t * p_config);
int  mpp_cam_osd_enable(_handle_t h_camera, int index);
void mpp_cam_osd_disable(_handle_t h_camera, int index);
void mpp_cam_osd_update(_handle_t h_camera, int index, char * data);

#ifdef __cplusplus
}
#endif

#endif  // __LIND_CAMERA__

